package tagcloud;

import Jama.Matrix;
import Jama.SingularValueDecomposition;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.List;
import tagcloud.component.DrawBox;
import tagcloud.component.Word;

/**
 *
 * @author thong
 */
public class LatentSemantic {

    List<Word> words1;
    List<Word> words2;
    List<Word> words3;
    String name1;
    String name2;
    String name3;
    List<String> allWords;
    List<DrawBox> allCommonWords;
    DrawBox[] journaux;

    double[][] ar;

    public LatentSemantic(List<Word> words1, List<Word> words2, List<Word> words3, String name1, String name2, String name3) {
        this.words1 = words1;
        this.words2 = words2;
        this.words3 = words3;
        this.name1 = name1;
        this.name2 = name2;
        this.name3 = name3;

        allWords = new LinkedList<>();
        for (Word w : words1) {
            if (!allWords.contains(w.word)) {
                allWords.add(w.word);
            }
        }
        for (Word w : words2) {
            if (!allWords.contains(w.word)) {
                allWords.add(w.word);
            }
        }
        for (Word w : words3) {
            if (!allWords.contains(w.word)) {
                allWords.add(w.word);
            }
        }

        allCommonWords = new LinkedList<>();
        for (String w : allWords) {
            int count = 0;
            if (getWordFrequence(w, words1) > 0) {
                count++;
            }
            if (getWordFrequence(w, words2) > 0) {
                count++;
            }
            if (getWordFrequence(w, words3) > 0) {
                count++;
            }
            if (count >= 2) {
                DrawBox b = new DrawBox();
                b.word = w;
                allCommonWords.add(b);
            }
        }

        ar = new double[allCommonWords.size()][4];
        for (int i = 0; i < allCommonWords.size(); i++) {
            String word = allCommonWords.get(i).word;
            ar[i][0] = getWordFrequence(word, words1);
            ar[i][1] = getWordFrequence(word, words2);
            ar[i][2] = getWordFrequence(word, words3);
            ar[i][3] = getWordFrequence(word, words3);
            System.out.println(word);
        }

        Jama.Matrix matrixWord = new Jama.Matrix(ar);
        SingularValueDecomposition s = matrixWord.svd();
        System.out.print("U = ");
        Matrix U = s.getU();
        U.print(9, 6);
        System.out.print("Sigma = ");
        Matrix S = s.getS();
        S.print(9, 6);
        System.out.print("V = ");
        Matrix V = s.getV();
        V.print(9, 6);

        double[][] US = tagcloud.component.Matrix.multiply(U.getArray(), S.getArray());
        double[][] SV = tagcloud.component.Matrix.multiply(S.getArray(), V.getArray());

        //get poisitions
        for (int i = 0; i < allCommonWords.size(); i++) {
            DrawBox b = allCommonWords.get(i);
            b.rect.x = (int) US[i][0];
            b.rect.y = (int) US[i][1];
        }

        journaux = new DrawBox[3];
        journaux[0] = new DrawBox();
        journaux[0].word = name1;
        journaux[0].rect.x = (int) SV[0][0];
        journaux[0].rect.y = (int) SV[1][0];

        journaux[1] = new DrawBox();
        journaux[1].word = name2;
        journaux[1].rect.x = (int) SV[0][1];
        journaux[1].rect.y = (int) SV[1][1];

        journaux[2] = new DrawBox();
        journaux[2].word = name3;
        journaux[2].rect.x = (int) SV[0][2];
        journaux[2].rect.y = (int) SV[1][2];
    }
    
    final int MAX_WIDTH=400;
    final int MAX_HEIGHT=400;
    final int v_gap=50;
    final int h_gap=50;

    public BufferedImage getImage() {
        Font font = new Font("Tahoma", Font.BOLD, 20);
        //add three journaux into list
        for (DrawBox b : journaux)
        {
            b.font=font;
            b.color=Color.RED;
            allCommonWords.add(b);
        }
        
        //repositioning within frame
        double minX = allCommonWords.get(0).rect.x;
        double maxX = allCommonWords.get(0).rect.x;
        double minY = allCommonWords.get(0).rect.y;
        double maxY = allCommonWords.get(0).rect.y;
        for (DrawBox b : allCommonWords) {
            if (b.rect.x > maxX) {
                maxX = b.rect.x;
            }
            if (b.rect.y > maxY) {
                maxY = b.rect.y;
            }
            if (b.rect.x < minX) {
                minX = b.rect.x;
            }
            if (b.rect.y < minY) {
                minY=b.rect.y;
            }
        }        

        double ratio;
        {
            double deltaX = maxX - minX;
            double deltaY = maxY - minY;

            if (MAX_WIDTH / deltaX > MAX_HEIGHT / deltaY) {
                ratio = MAX_HEIGHT / deltaY;
            } else {
                ratio = MAX_WIDTH / deltaX;
            }
        }

        for (DrawBox b : allCommonWords) {
            b.rect.x-=minX;
            b.rect.y-=minY;
            b.rect.x*= ratio;
            b.rect.y*= ratio;
        }
                
        BufferedImage image = new BufferedImage(MAX_WIDTH+2*v_gap, MAX_HEIGHT+2*h_gap, BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setColor(new Color(0.5f,0.5f,0.5f,0.05f));
        g.fillRect(0, 0, image.getWidth(), image.getHeight());
        for (DrawBox b : allCommonWords)
        {
            g.setFont(b.font);
            g.setColor(b.color);
            g.fillOval(b.rect.x+v_gap, b.rect.y+h_gap, 6,6);
            g.drawString(b.word, b.rect.x+v_gap, b.rect.y+h_gap);
        }
        return image;
    }

    public double getX2Statistic() {
        double result = 0;
        double total = 0;

        double[] totalFrequence = new double[3];
        for (String w : allWords) {
            total += getWordFrequence(w, words1) + getWordFrequence(w, words2) + getWordFrequence(w, words3);
        }

        totalFrequence[0] = 0;
        for (Word w : words1) {
            totalFrequence[0] += w.frequency;
        }
        totalFrequence[1] = 0;
        for (Word w : words2) {
            totalFrequence[1] += w.frequency;
        }
        totalFrequence[2] = 0;
        for (Word w : words3) {
            totalFrequence[2] += w.frequency;
        }
        total = totalFrequence[0] + totalFrequence[1] + totalFrequence[2];
        for (String w : allWords) {
            double nominator;
            double nominator1 = getWordFrequence(w, words1);
            double nominator2 = getWordFrequence(w, words2);
            double nominator3 = getWordFrequence(w, words3);
            nominator = nominator1 + nominator2 + nominator3;
            double expected1 = totalFrequence[0] * nominator / total;
            double expected2 = totalFrequence[1] * nominator / total;
            double expected3 = totalFrequence[2] * nominator / total;
            result += sqr(nominator1 - expected1) / expected1 + sqr(nominator2 - expected2) / expected2 + sqr(nominator3 - expected3) / expected3;
        }
        return result;
    }

    private double getWordFrequence(String word, List<Word> list) {
        for (Word w : list) {
            if (w.word.equals(word)) {
                return w.frequency;
            }
        }
        return 0;
    }

    private double sqr(double value) {
        return value * value;
    }
}
